#include<iostream>
#include<thread>
#include<mutex>
#include<memory>


using namespace std;
//
//
////int div()
////{
////	int a, b;
////	cin >> a >> b;
////	if (b == 0)
////		throw invalid_argument("除0错误");
////	return a / b;
////}
////void Func()
////{
////	// 1、如果p1这里new 抛异常会如何？ --- 不需要管
////	// 2、如果p2这里new 抛异常会如何？ --- 需要释放p1
////	// 3、如果div调用这里又会抛异常会如何？ --- 需要释放p1、p2 
////	int* p1 = new int;
////	int* p2 = new int;
////	cout << div() << endl;
////	delete p1;
////	delete p2;
////}
////int main()
////{
////	try
////	{
////		Func();
////	}
////	catch (exception& e)
////	{
////		cout << e.what() << endl;
////
////	}
////	return 0;
////}
//
//
//// 使用RAII思想设计的SmartPtr类
//template<class T>
//class SmartPtr
//{
//public:
//	SmartPtr(T* ptr)//获取资源
//		:_ptr(ptr)
//	{}
//
//	~SmartPtr()//出作用域自动释放资源
//	{
//		cout << "delete:" << _ptr << endl;
//		delete _ptr;
//	}
//
//	// 像指针一样使用
//	T& operator*()
//	{
//		return *_ptr;
//	}
//
//	T* operator->()
//	{
//		return _ptr;
//	}
//private:
//	//封装一个原生指针
//	T* _ptr;
//};
//
////智能指针原理总结：
////1. RAII特性
////2. 重载operator * 和opertaor->，具有像指针一样的行为。
//
//int div()
//{
//	int a, b;
//	cin >> a >> b;
//	if (b == 0)
//		throw invalid_argument("除0错误");
//	return a / b;
//}
//
//void Func()
//{
//	SmartPtr<int> sp1(new int);// 出作用域会自动调用析构函数，释放资源。
//	SmartPtr<int> sp2(new int);
//	SmartPtr<int> sp3(new int);
//	cout << div() << endl;
//}
////int main()
////{
////	try
////	{
////		Func();
////	}
////	catch (exception& e)
////	{
////		cout << e.what() << endl;
////
////	}
////	return 0;
////}
//
////int main()
////{
////	SmartPtr<int> sp1(new int);
////	SmartPtr<int> sp2(sp1);
////	return 0;
////}
////
//
//// C++98 管理权转移 auto_ptr
//namespace bit
//{
//	template<class T>
//	class auto_ptr
//	{
//	public:
//		auto_ptr(T* ptr)
//			:_ptr(ptr)
//		{}
//		auto_ptr(auto_ptr<T>& sp)
//			:_ptr(sp._ptr)
//		{
//			// 管理权转移
//			sp._ptr = nullptr;
//		}
//		auto_ptr<T>& operator=(auto_ptr<T>& ap)
//		{
//			// 检测是否为自己给自己赋值
//			if (this != &ap)
//			{
//				// 释放当前对象中资源
//				if (_ptr)
//					delete _ptr;
//				// 转移ap中资源到当前对象中
//				_ptr = ap._ptr;
//				ap._ptr = NULL;
//			}
//			return *this;
//		}
//		~auto_ptr()
//		{
//			if (_ptr)
//			{
//				cout << "delete:" << _ptr << endl;
//				delete _ptr;
//			}
//		}
//		T& operator*()
//		{
//			return *_ptr;
//		}
//		T* operator->()
//		{
//			return _ptr;
//		}
//	private:
//		T* _ptr;
//	};
//}
////
////// 结论：auto_ptr是一个失败设计，很多公司明确要求不能使用auto_ptr
////int main()
////{
//// std::auto_ptr<int> sp1(new int);
//// std::auto_ptr<int> sp2(sp1); // 管理权转移 --- 虽然不会奔溃了，但是sp1被悬空了。
////
//// // sp1悬空
//// *sp2 = 10;
//// cout << *sp2 << endl;// 出现了空指针的问题
//// cout << *sp1 << endl;
//// return 0;
////}
//
//
//// unique_ptr/scoped_ptr 
//// 原理：简单粗暴 -- 防拷贝
//namespace bit
//{
//	template<class T>
//	class unique_ptr //--->在头文件<memory>中
//	{
//	public:
//		unique_ptr(T* ptr)
//			:_ptr(ptr)
//		{}
//
//		~unique_ptr()
//		{
//			if (_ptr)
//			{
//				cout << "delete:" << _ptr << endl;
//				delete _ptr;
//			}
//		}
//		// 像指针一样使用
//		T& operator*()
//		{
//			return *_ptr;
//		}
//		T* operator->()
//		{
//			return _ptr;
//		}
//
//		unique_ptr(const unique_ptr<T>& sp) = delete;
//		unique_ptr<T>& operator=(const unique_ptr<T>& sp) = delete;
//	private:
//		T* _ptr;
//	};
//}
//
////int main()
////{
//// /*bit::unique_ptr<int> sp1(new int);
//// bit::unique_ptr<int> sp2(sp1);*/
////
//// std::unique_ptr<int> sp1(new int);
//// //std::unique_ptr<int> sp2(sp1);
////
//// return 0;
////}
//
//namespace bit
//{
//	template<class T>
//	class shared_ptr
//	{
//	public:
//		shared_ptr(T* ptr = nullptr)
//			:_ptr(ptr)
//			, _pRefCount(new int(1))
//			, _pmtx(new mutex)
//		{}
//		shared_ptr(const shared_ptr<T>& sp)
//			:_ptr(sp._ptr)
//			, _pRefCount(sp._pRefCount)
//			, _pmtx(sp._pmtx)
//		{
//			AddRef();
//		}
//		void Release()
//		{
//			_pmtx->lock();
//			bool flag = false;
//			if (--(*_pRefCount) == 0 && _ptr)
//			{
//				cout << "delete:" << _ptr << endl;
//				delete _ptr;
//				delete _pRefCount;
//				flag = true;
//			}
//			_pmtx->unlock();
//			if (flag == true)
//			{
//				delete _pmtx;
//			}
//		}
//		void AddRef()
//		{
//			_pmtx->lock();
//			++(*_pRefCount);
//			_pmtx->unlock();
//		}
//		shared_ptr<T>& operator=(const shared_ptr<T>& sp)
//		{
//			//if (this != &sp)
//			if (_ptr != sp._ptr)
//			{
//				Release();
//				_ptr = sp._ptr;
//				_pRefCount = sp._pRefCount;
//				_pmtx = sp._pmtx;
//				AddRef();
//			}
//			return *this;
//		}
//		int use_count()
//		{
//			return *_pRefCount;
//		}
//		~shared_ptr()
//		{
//			Release();
//		}
//		// 像指针一样使用
//		T& operator*()
//		{
//			return *_ptr;
//		}
//		T* operator->()
//		{
//			return _ptr;
//		}
//		T* get() const
//		{
//			return _ptr;
//		}
//
//	private:
//		T* _ptr;
//		int* _pRefCount;
//		mutex* _pmtx;
//	};
//}
//
//template<class T>
//class shared_ptr
//{
//public:
//	//...//
//	//...//
//private:
//	T* _ptr;
//	int* _pRefCount;
//};
//
//
//int main()
//{
//
//	return 0;
//}
//
//
//void SharePtrFunc(bit::shared_ptr<Date>& sp, size_t n, mutex& mtx)
//{
//	cout << sp.get() << endl;
//
//	for (size_t i = 0; i < n; ++i)
//	{
//		// 这里智能指针拷贝会++计数，智能指针析构会--计数，这里是线程安全的。
//		bit::shared_ptr<Date> copy(sp);
//
//		// 这里智能指针访问管理的资源，不是线程安全的。所以我们看看这些值两个线程++了2n次，但是最终看到的结果，并一定是加了2n
//
//		{
//			unique_lock<mutex> lk(mtx);
//			copy->_year++;
//			copy->_month++;
//			copy->_day++;
//		}
//
//		//...
//		//cout<<"hello"<<endl;
//	}
//}
///////////////////


//template<class T>
//class shared_ptr
//{
//public:
//	shared_ptr(T* ptr)
//		:_ptr(ptr)
//		, _pRefCount(new int(1))//引用计数初始值设为1
//	{}
//
//	//shared_ptr支持拷贝构造和赋值操作符重载
//	shared_ptr(const shared_ptr<T>& sp)
//		:_ptr(sp._ptr)
//		, _pRefCount(sp._pRefCount)
//	{
//		++(*_pRefCount);//++引用计数
//	}
//
//	shared_ptr<T>& operator=(const shared_ptr<T>& sp)
//	{
//		//if (this != &sp) 
//		if (_ptr != sp._ptr)
//		{
//			//--旧资源的_pRefCount
//			if (--(*_pRefCount) == 0 && _ptr)
//			{
//				cout << "delete:" << _ptr << endl;
//				delete _ptr;
//				delete _pRefCount;
//			}
//
//			//指向新资源
//			_ptr = sp._ptr;
//			_pRefCount = sp._pRefCount;
//
//			//++新资源的_pRefCount
//			++(*_pRefCount);
//		}
//		return *this;
//	}
//
//	~shared_ptr()
//	{
//		//引用计数为0时才进去并释放资源
//		if (--(*_pRefCount) == 0 && _ptr)
//		{
//			cout << "delete:" << _ptr << endl;
//			delete _ptr;
//			delete _pRefCount;
//		}
//	}
//
//	// 像指针一样使用
//	T& operator*()
//	{
//		return *_ptr;
//	}
//	T* operator->()
//	{
//		return _ptr;
//	}
//private:
//	T* _ptr;
//	int* _pRefCount;
//};

//template<class T>
//class shared_ptr
//{
//public:
//	shared_ptr(T* ptr = nullptr)
//		:_ptr(ptr)
//		, _pRefCount(new int(1))
//		, _pmtx(new mutex)
//	{}
//	shared_ptr(const shared_ptr<T>& sp)
//		:_ptr(sp._ptr)
//		, _pRefCount(sp._pRefCount)
//		, _pmtx(sp._pmtx)
//	{
//		AddRef();
//	}
//	void Release()
//	{
//		_pmtx->lock();
//		bool flag = false;//--前先上锁
//		if (--(*_pRefCount) == 0 && _ptr)
//		{
//			cout << "delete:" << _ptr << endl;
//			delete _ptr;
//			delete _pRefCount;
//			flag = true;//不能在这里直接delete锁的那块空间，因为下面还要unlock
//						//在这里先把flag置为true
//		}
//		_pmtx->unlock();
//		if (flag == true)
//		{
//			delete _pmtx;
//		}
//	}
//	void AddRef()
//	{
//		_pmtx->lock();//++前先上锁
//		++(*_pRefCount);
//		_pmtx->unlock();
//	}
//	shared_ptr<T>& operator=(const shared_ptr<T>& sp)
//	{
//		//if (this != &sp)
//		if (_ptr != sp._ptr)
//		{
//			Release();//用Release进行引用计数--，保证线程安全
//			_ptr = sp._ptr;
//			_pRefCount = sp._pRefCount;
//			_pmtx = sp._pmtx;
//			AddRef();//用AddRef进行引用计数++，保证线程安全
//		}
//		return *this;
//	}
//	T& operator*()
//	{
//		return *_ptr;
//	}
//	T* operator->()
//	{
//		return _ptr;
//	}
//	T* get() const
//	{
//		return _ptr;
//	}
//	int use_count()
//	{
//		return *_pRefCount;
//	}
//	~shared_ptr()
//	{
//		Release();
//	}
//	// 像指针一样使用
//
//private:
//	T* _ptr;
//	int* _pRefCount;
//	mutex* _pmtx;//构造函数时new一块空间
//};

//struct ListNode
//{
//	int _val;
//	std::shared_ptr<ListNode> _next;
//	std::shared_ptr<ListNode> _prev;
//
//	~ListNode()
//	{
//		cout << "~ListNode()" << endl;
//	}
//};
//
//std::shared_ptr<ListNode> n1 = new ListNode;
//std::shared_ptr<ListNode> n2 = new ListNode;
//struct ListNode
//{
//	int _data;
//	shared_ptr<ListNode> _prev;
//	shared_ptr<ListNode> _next;
//	~ListNode() 
//	{
//		cout << "~ListNode()" << endl;
//	}
//};

struct ListNode
{
	int _data;
	weak_ptr<ListNode> _prev;
	weak_ptr<ListNode> _next;
	~ListNode() 
	{ 
		cout << "~ListNode()" << endl;
	}
};

class A
{
private:
	int _a1 = 0;
	int _a2 = 0;
};

//
//A* p = new A[10];
//delete p;
//
//
//int main()
//{
//	shared_ptr<ListNode> node1(new ListNode);
//	shared_ptr<ListNode> node2(new ListNode);
//	node1->_next = node2;
//	node2->_prev = node1;
//	return 0;
//}

// 仿函数的删除器
template<class T>
struct FreeFunc {
	void operator()(T* ptr)
	{
		cout << "free:" << ptr << endl;
		free(ptr);
	}
};
template<class T>
struct DeleteArrayFunc {
	void operator()(T* ptr)
	{
		cout << "delete[]" << ptr << endl;
		delete[] ptr;
	}
};

struct DeleteFileFunc
{
	void operator()(FILE* ptr)
	{
		cout << "fclose:" << ptr << endl;
		fclose(ptr);
	}
};

// 释放方式由删除器D决定
template<class T, class D = default_delete<T>>
class unique_ptr
{
public:
	unique_ptr(T* ptr)
		:_ptr(ptr)
	{}

	~unique_ptr()
	{
		if (_ptr)
		{
			//cout << "delete:" << _ptr << endl;
			//delete _ptr;
			D del;
			del(_ptr);
		}
	}

	// 像指针一样使用
	T& operator*()
	{
		return *_ptr;
	}
	T* operator->()
	{
		return _ptr;
	}

	unique_ptr(const unique_ptr<T>& sp) = delete;
	unique_ptr<T>& operator=(const unique_ptr<T>& sp) = delete;

private:
	T* _ptr;
};

int main()
{
	// 删除器在类模板参数给 -- 类型
	unique_ptr<A> up1(new A);
	unique_ptr<A, DeleteArrayFunc<A>> up2(new A[10]);
	unique_ptr<FILE, DeleteFileFunc> up3(fopen("test.txt", "w"));

	// 删除器在构造函数的参数给 -- 对象
	std::shared_ptr<int> sp1((int*)malloc(4), FreeFunc<int>());
	std::shared_ptr<int> sp2((int*)malloc(4), DeleteArrayFunc<int>());
	std::shared_ptr<A> sp4(new A[10], [](A* p) {delete[] p; });//给lambda表达式
	std::shared_ptr<FILE> sp5(fopen("test.txt", "w"), [](FILE* p){fclose(p); });

	return 0;
}

